package Box2D.Collision
{
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Common.b2Wrapper;
	
	/// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt.
	/// A dynamic tree arranges data in a binary tree to accelerate
	/// queries such as volume queries and ray casts. Leafs are proxies
	/// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor
	/// so that the proxy AABB is bigger than the client object. This allows the client
	/// object to move by small amounts without triggering a tree update.
	///
	/// Nodes are pooled and relocatable, so we use node indices rather than pointers.
	public class b2DynamicTree extends b2Wrapper
	{
		public static const b2_nullNode:int = -1;
		private var _queryCallback:Function;
		private var _rayCastCallback:Function;
		public function b2DynamicTree()
		{
			super(callDirect('b2DynamicTree_new',this));
		}
		public virtual function QueryCallback(proxyId:int):Boolean{
			if(_queryCallback!=null)
				return _queryCallback(proxyId);
			else
				return true;				
		}
		public virtual function RayCastCallback(input:b2RayCastInput,proxyId:int):Number{
			if(_rayCastCallback!=null)
				return _rayCastCallback(input,proxyId);
			else
				return input.maxFraction;
		}
		public function cRayCastCallback(inputPtr:Object,proxyId:int):Number{
			var input:b2RayCastInput = new b2RayCastInput(inputPtr);
			return RayCastCallback(input,proxyId);
		}
		
		/// Create a proxy. Provide a tight fitting AABB and a userData pointer.
		public function CreateProxy(aabb:b2AABB,userData:*):int
		{
			return call('b2DynamicTree_CreateProxy',aabb.wrapper,userData);
		}
		
		/// Destroy a proxy. This asserts if the id is invalid.
		public function DestroyProxy(proxyId:int):void{
			call('b2DynamicTree_DestroyProxy',proxyId);
		}
		
		/// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB,
		/// then the proxy is removed from the tree and re-inserted. Otherwise
		/// the function returns immediately.
		/// @return true if the proxy was re-inserted.
		public function MoveProxy(proxyId:int,aabb1:b2AABB,displacement:b2Vec2):Boolean{
			return call('b2DynamicTree_MoveProxy',proxyId,aabb1.wrapper,displacement.wrapper);
		}

		/// Get proxy user data.
		/// @return the proxy user data or 0 if the id is invalid.
		public function GetUserData(proxyId:int):*{
			return call('b2DynamicTree_GetUserData',proxyId);
		}

		/// Get the fat AABB for a proxy.
		public function GetFatAABB(proxyId:int):b2AABB{
			return new b2AABB(call('b2DynamicTree_GetFatAABB',proxyId));				
		}
		
		/// Query an AABB for overlapping proxies. The callback class
		/// is called for each proxy that overlaps the supplied AABB.
		public function Query(callback:Function,aabb:b2AABB):void{
			_queryCallback=callback;
			call('b2DynamicTree_Query',aabb.wrapper);
		}		

		/// Ray-cast against the proxies in the tree. This relies on the callback
		/// to perform a exact ray-cast in the case were the proxy contains a shape.
		/// The callback also performs the any collision filtering. This has performance
		/// roughly equal to k * log(n), where k is the number of collisions and n is the
		/// number of proxies in the tree.
		/// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1).
		/// @param callback a callback class that is called for each proxy that is hit by the ray.
		public function RayCast(callback:Function,input:b2RayCastInput):void{
			_rayCastCallback = callback;
			call('b2DynamicTree_RayCast',input.wrapper);
		}

		/// Validate this tree. For testing.
		public function Validate():void{
			call('b2DynamicTree_Validate');
		}

		/// Compute the height of the binary tree in O(N) time. Should not be
		/// called often.
		public function GetHeight():int{
			return call('b2DynamicTree_GetHeight');
		}

		/// Get the maximum balance of an node in the tree. The balance is the difference
		/// in height of the two children of a node.
		public function GetMaxBalance():int{
			return call('b2DynamicTree_GetMaxBalance');
		}

		/// Get the ratio of the sum of the node areas to the root area.
		public function GetAreaRatio():Number{
			return call('b2DynamicTree_GetAreaRatio');
		}

		/// Build an optimal tree. Very expensive. For testing.
		public function RebuildBottomUp():void{
			call('b2DynamicTree_RebuildBottomUp');
		}
	}
}